package edu.gatech.mobile.scene.provider.impl;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Point;
import android.location.Location;
import android.location.LocationManager;
import android.widget.HorizontalScrollView;
import edu.gatech.mobile.scene.model.ImageInfo;
import edu.gatech.mobile.scene.model.ImageInfoConstants;
import edu.gatech.mobile.scene.model.MaskInfo;

/**
 * Database helper for accessing data in the ImageInfo table.
 * @author Jing
 *
 */

public class ImageInfoDBImpl {
	private Context mContext;
	private static MaskInfoDBImpl maskDB; 
	
	public ImageInfoDBImpl(Context context){
		mContext=context;
		maskDB = new MaskInfoDBImpl(mContext);
	}
	
	/**
	 * Store the image in the database.
	 * @param imageInfo image to be stored
	 */
	public void putImage(ImageInfo imageInfo){
		ContentResolver resolver = mContext.getContentResolver();
		resolver.insert(ImageInfoTable.CONTENT_URI, getQueryValues(imageInfo));
	}
	
	/**
	 * Get a cursor with all images
	 * @return the cursor with all images
	 */
	public Cursor getAllImagesCursor(){
		ContentResolver resolver = mContext.getContentResolver();
		Cursor cursor =resolver.query(ImageInfoTable.CONTENT_URI, null, null, null, null);
		return cursor;
	}
	
	/**
	 * Get all images stored in the database.
	 * @param getUsed the boolean flag indicated the image should be used for training or not.
	 * @return all the images in the database.
	 */
	public List<ImageInfo> getAllImages(boolean getUsed){
		List<ImageInfo> items = new ArrayList<ImageInfo>();
		ContentResolver resolver = mContext.getContentResolver();
		
		String where =null;
		if(getUsed){
			where= ImageInfoTable.USE + " = "+1;
		}
		Cursor cursor =resolver.query(ImageInfoTable.CONTENT_URI, null, where, null, null);
		
		while (cursor != null && cursor.getCount() > 0 && !cursor.isLast()){
			ImageInfo item = fillFromCursor(cursor);
			items.add(item);
		}
		safelyCloseCursor(cursor);

		return items;
	}
	
	/**
	 * database cursor with all the images flag set to use
	 * @param getUsed booelan flag indicating if the image should be used for training 
	 * @return database cursor.
	 */
	public Cursor getUseImagesCursor(boolean getUsed){
		ContentResolver resolver = mContext.getContentResolver();
		String where =null;
		if(getUsed){
			where= ImageInfoTable.USE + " = "+1;
		}
		Cursor cursor =resolver.query(ImageInfoTable.CONTENT_URI, null, where, null, null);
		return cursor;
	}
	
	/**
	 * Remove the given image
	 * @param imageInfo image to be removed.
	 */
	public void removeImage(ImageInfo imageInfo){
		ContentResolver resolver = mContext.getContentResolver();
		final String where= ImageInfoTable.FILE_NAME + "='"+imageInfo.getFileName()+"'";
		resolver.delete(ImageInfoTable.CONTENT_URI, where, null);
	}
		
	/**
	 * Get a image based on the image name
	 * @param imageName the image name of the image to be retrieved.
	 * @return the ImageInfo with the imageName
	 */
	public ImageInfo getImageByName(String imageName){
		String where = ImageInfoTable.FILE_NAME + "='"+imageName +"'";
		ImageInfo item =null;
		ContentResolver resolver = mContext.getContentResolver();
		Cursor cursor =resolver.query(ImageInfoTable.CONTENT_URI, null, where, null, null);
		while (cursor != null && cursor.getCount() > 0 && !cursor.isLast()){
			item = fillFromCursor(cursor);
		}
		safelyCloseCursor(cursor);
		return item;
	}
	
	/**
	 * Updating the given image in the database. 
	 * @param imageInfo the image to be updated.
	 */
	public void updateImage(ImageInfo imageInfo){
		String where = ImageInfoTable.FILE_NAME + "='"+imageInfo.getFileName() +"'";
		ContentValues fields = getQueryValues(imageInfo);
		ContentResolver resolver = mContext.getContentResolver();
		resolver.update(ImageInfoTable.CONTENT_URI, fields, where, null);
	}
	
	
	/**
	 * Table containing table columnn name and corresponding value.
	 * @param imageInfo imageInfo values to put into the table
	 * @return the table containing values and column name
	 */
	private ContentValues getQueryValues(ImageInfo imageInfo) {
		Long time;
		if((time=imageInfo.getTimeTaken()) == null){
			time = System.currentTimeMillis();
		}
		ContentValues values = new ContentValues();
		int intUse = imageInfo.isUse()?1:0;
		values.put(ImageInfoTable.USE, intUse);
		values.put(ImageInfoTable.TIME_POSTED, time);
		values.put(ImageInfoTable.FILE_NAME, imageInfo.getFileName());
		if(imageInfo.getLocation()!=null){
			values.put(ImageInfoTable.LATITUDE, imageInfo.getLocation().getLatitude());
			values.put(ImageInfoTable.LONGITUDE, imageInfo.getLocation().getLongitude());
			values.put(ImageInfoTable.ALTITUDE, imageInfo.getLocation().getAltitude());
		}
		values.put(ImageInfoTable.ACCELEROMETER_X, imageInfo.getAccelerometer()[ImageInfoConstants.XIndex]);
		values.put(ImageInfoTable.ACCELEROMETER_Y, imageInfo.getAccelerometer()[ImageInfoConstants.YIndex]);
		values.put(ImageInfoTable.ACCELEROMETER_Z, imageInfo.getAccelerometer()[ImageInfoConstants.ZIndex]);
		
		values.put(ImageInfoTable.HORIZON_LEFT_X, imageInfo.getHorizonPoints()[0].x);
		values.put(ImageInfoTable.HORIZON_LEFT_Y, imageInfo.getHorizonPoints()[0].y);
		values.put(ImageInfoTable.HORIZON_RIGHT_X, imageInfo.getHorizonPoints()[1].x);
		values.put(ImageInfoTable.HORIZON_RIGHT_Y, imageInfo.getHorizonPoints()[1].y);
		
		values.put(ImageInfoTable.MAGNETIC_X, imageInfo.getMagneticField()[ImageInfoConstants.XIndex]);
		values.put(ImageInfoTable.MAGNETIC_Y, imageInfo.getMagneticField()[ImageInfoConstants.YIndex]);
		values.put(ImageInfoTable.MAGNETIC_Z, imageInfo.getMagneticField()[ImageInfoConstants.ZIndex]);
		if(imageInfo.getOrientation() != null){
			values.put(ImageInfoTable.ORIENTATION_AZIMUTH, imageInfo.getOrientation()[ImageInfoConstants.AzimuthIndex]);
			values.put(ImageInfoTable.ORIENTATION_PITCH, imageInfo.getOrientation()[ImageInfoConstants.Pitchindex]);
			values.put(ImageInfoTable.ORIENTATION_ROLL, imageInfo.getOrientation()[ImageInfoConstants.RollIndex]);
		}
		
		values.put(ImageInfoTable.FOCAL_LENGTH, imageInfo.getFocalLength());
		values.put(ImageInfoTable.WHITE_BALANCE, imageInfo.getWhiteBalance());
		values.put(ImageInfoTable.CAMERA_PARAMS, imageInfo.getCameraParams());
		return values;
	}
	
	/**
	 * Create an ImageInfo with the values in the cursor.
	 * @param cursor cursor with a row of data
	 * @return the ImageInfo with values in the data.
	 */
	public static ImageInfo fillFromCursor(Cursor cursor) {
		cursor.moveToNext();
		ImageInfo imageInfo = new ImageInfo();
		imageInfo.setFileName(cursor.getString(cursor.getColumnIndex(ImageInfoTable.FILE_NAME)));
		int useInt = cursor.getInt(cursor.getColumnIndex(ImageInfoTable.USE));
		imageInfo.setUse((useInt!=0)?true:false);
		imageInfo.setTimeTaken(cursor.getLong(cursor.getColumnIndex(ImageInfoTable.TIME_POSTED)));
		
		
		Location loc = new Location(LocationManager.GPS_PROVIDER);
		double lat = cursor.getDouble(cursor.getColumnIndex(ImageInfoTable.LATITUDE));
		double lon = cursor.getDouble(cursor.getColumnIndex(ImageInfoTable.LONGITUDE));
		double alt = cursor.getDouble(cursor.getColumnIndex(ImageInfoTable.ALTITUDE));
		loc.setLatitude(lat);
		loc.setLongitude(lon);
		loc.setAltitude(alt);
	
		float accelX = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.ACCELEROMETER_X));
		float accelY = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.ACCELEROMETER_Y));
		float accelZ = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.ACCELEROMETER_Z));
		float[] accelValues = new float[3];
		accelValues[ImageInfoConstants.XIndex] = accelX;
		accelValues[ImageInfoConstants.YIndex] = accelY;
		accelValues[ImageInfoConstants.ZIndex] = accelZ;
		imageInfo.setAccelerometer(accelValues);
		
		Point[] horizonPoints = new Point[2];
		Point p1 = new Point(cursor.getInt(cursor.getColumnIndex(ImageInfoTable.HORIZON_LEFT_X)), cursor.getInt(cursor.getColumnIndex(ImageInfoTable.HORIZON_LEFT_Y)));
		Point p2 = new Point(cursor.getInt(cursor.getColumnIndex(ImageInfoTable.HORIZON_RIGHT_X)), cursor.getInt(cursor.getColumnIndex(ImageInfoTable.HORIZON_RIGHT_Y)));
		horizonPoints[0] = p1;
		horizonPoints[1] = p2;
		imageInfo.setHorizonPoints(horizonPoints);
		
		imageInfo.setFocalLength(cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.FOCAL_LENGTH)));
		imageInfo.setWhiteBalance(cursor.getInt(cursor.getColumnIndex(ImageInfoTable.WHITE_BALANCE)));

		float[] orientation = new float[3];
		orientation[ImageInfoConstants.AzimuthIndex] = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.ORIENTATION_AZIMUTH));
		orientation[ImageInfoConstants.Pitchindex] = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.ORIENTATION_PITCH));
		orientation[ImageInfoConstants.RollIndex] = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.ORIENTATION_ROLL));
		imageInfo.setOrientation(orientation);
		
		
		float[] magneticValues = new float[3];
		magneticValues[ImageInfoConstants.XIndex] = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.MAGNETIC_X));
		magneticValues[ImageInfoConstants.YIndex] = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.MAGNETIC_Y));
		magneticValues[ImageInfoConstants.ZIndex] = cursor.getFloat(cursor.getColumnIndex(ImageInfoTable.MAGNETIC_Z));
		imageInfo.setMagneticField(magneticValues);
		
		List<MaskInfo> masks = maskDB.getMasksforImage(imageInfo.getFileName());
		imageInfo.setMasks(masks);
		
		return imageInfo;
		
	}
	
	private void safelyCloseCursor(Cursor cur) {
		if(cur != null && cur.isClosed() == false)
			cur.close();
	}
}
